package com.mars.foodserver.interceptor;

import com.mars.foodserver.constant.Constant;
import com.mars.foodserver.service.ISysIgnorePathService;
import com.mars.foodserver.utils.JwtUtil;
import com.mars.foodserver.utils.TokenUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;


/**
 * 采用拦截器的方式来做鉴权
 *
 * @author wq
 * @date 2021-06-15 20:41
 */
@Component
@Slf4j
public class AuthenticationInterceptor implements HandlerInterceptor {

    @Resource
    private TokenUtils tokenUtils;

    @Resource
    private ISysIgnorePathService sysIgnorePathService;


    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        //处理跨域
        executeCors(response);
        String servletPath = request.getServletPath();
        //放行路径
        Boolean b = sysIgnorePathService.isIgnorePath(servletPath);
        if (b) {
            return true;
        }
        log.info("\n【请求方式】:{}\n【请求路径】:{}", request.getMethod(), request.getServletPath());
        if (servletPath.startsWith(Constant.ADMIN_CONTEXT_PATH)) {
            //后台管理系统拦截
            return adminInterceptor(request, response);
        } else {
            //APP登录拦截
            return appInterceptor(request, response);
        }
    }

    /**
     * 处理跨域
     *
     * @param response 响应参数
     */
    private void executeCors(HttpServletResponse response) {
        response.setHeader("Access-Control-Allow-Origin", "*");
        response.setHeader("Access-Control-Allow-Methods", "POST, GET, OPTIONS, DELETE, HEAD");
        response.setHeader("Access-Control-Max-Age", "3600");
        response.setHeader("Access-Control-Allow-Headers", "*");
    }

    /**
     * APP登录拦截
     *
     * @param request  请求参数
     * @param response 详情参数
     * @return boolean
     */
    private boolean appInterceptor(HttpServletRequest request, HttpServletResponse response) {

        String token = request.getHeader(Constant.ACCESS_TOKEN);
        if (StringUtils.isEmpty(token)) {
            log.error("未携带token,拦截，请求路径[{}][{}]", request.getMethod(), request.getServletPath());
            renderResponse(request, response);
            return false;
        }
        //校验令牌是否有效
        if (!JwtUtil.checkToken(token)) {
            log.error("未登录或登录已过期 请求路径[{}][{}]", request.getMethod(), request.getServletPath());
            expireLoginResponse(request, response);
            return false;
        }
        String userId = JwtUtil.getUserId(token);
        // 检验登录
        if (!tokenUtils.checkUserLogin(userId)) {
            log.error("拦截未登录 请求路径[{}][{}]", request.getMethod(), request.getServletPath());
            renderResponse(request, response);
            return false;
        }
        request.setAttribute(Constant.USER_ID, userId);
        return true;
    }


    /**
     * 后台管理登录拦截
     *
     * @param request  请求参数
     * @param response 详情参数
     * @return boolean
     */
    private boolean adminInterceptor(HttpServletRequest request, HttpServletResponse response) {

        String token = request.getHeader(Constant.ACCESS_TOKEN);
        if (StringUtils.isEmpty(token)) {
            log.error("未携带token,拦截，请求路径[{}][{}]", request.getMethod(), request.getServletPath());
            renderResponse(request, response);
            return false;
        }
        //校验令牌是否有效
        if (!JwtUtil.checkToken(token)) {
            log.error("未登录或登录已过期 请求路径[{}][{}]", request.getMethod(), request.getServletPath());
            expireLoginResponse(request, response);
            return false;
        }
        String userId = JwtUtil.getSysUserId(token);
        // 检验登录
        if (!tokenUtils.checkAdminUserLogin(userId)) {
            log.error("拦截未登录 请求路径[{}][{}]", request.getMethod(), request.getServletPath());
            renderResponse(request, response);
            return false;
        }
        request.setAttribute(Constant.SYS_USER_ID, userId);
        return true;
    }


    private void renderResponse(HttpServletRequest request, HttpServletResponse response) {
        response.setHeader("content-type", "application/json;charset=UTF-8 ");
        try {
            response.getWriter().println("{\"status\":401,\"msg\":\"你还未登录哦\",\"data\":null}");
            response.flushBuffer();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    private void expireLoginResponse(HttpServletRequest request, HttpServletResponse response) {
        response.setHeader("content-type", "application/json;charset=UTF-8 ");
        try {
            response.getWriter().println("{\"status\":401,\"msg\":\"登录已过期,请重新登录\",\"data\":null}");
            response.flushBuffer();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

}
